package io.github.cubelitblade.librarymanagementbackend.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.github.cubelitblade.librarymanagementbackend.entity.Book;
import io.github.cubelitblade.librarymanagementbackend.exception.BusinessException;
import io.github.cubelitblade.librarymanagementbackend.mapper.BookMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class BookService extends ServiceImpl<BookMapper, Book> {
    private final BookMapper bookMapper;

    @Autowired
    public BookService(BookMapper bookMapper) {
        this.bookMapper = bookMapper;
    }

    // 随机从book表获取n条数据
    public List<Book> getRandomBookList(int n) {
        LambdaQueryWrapper<Book> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.last("ORDER BY RAND() LIMIT " + n);
        return super.list(queryWrapper);
    }

    // 从book表获取借阅量前n位的数据
    public List<Book> getBooksByBorrowing(int n) {
        LambdaQueryWrapper<Book> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(Book::getBorrowCount).last("LIMIT " + n);
        return super.list(queryWrapper);
    }

    // 从book表获取收藏量前n位的数据
    public List<Book> getBooksByFavorite(int n) {
        LambdaQueryWrapper<Book> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(Book::getFavoriteCount).last("LIMIT " + n);
        return super.list(queryWrapper);
    }

    //根据categoriesId获取所有书籍
    public Page<Book> getBooksByCategoryId(Integer categoryId, int page, int size) {
        LambdaQueryWrapper<Book> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Book::getCategoryId, categoryId);
        Page<Book> bookPage = new Page<>(page, size);
        return bookMapper.selectPage(bookPage, queryWrapper);
    }

    //获取所有书籍
    public Page<Book> getAllBooks(int page, int size) {
        Page<Book> bookPage = new Page<>(page, size);
        return bookMapper.selectPage(bookPage, null);
    }


    /**
     * 更新书籍的数量。
     * <p>将 {@code bookId} 对应的书籍的数量更改为 {@code stock}。 <p/>
     *
     * @param bookId 待更新数量的书籍ID。
     * @param stock  目标数量。
     */
    public void updateBookStock(Integer bookId, Integer stock) {
        Book book = new Book();
        book.setId(bookId);
        book.setStock(stock);
        if (bookMapper.updateById(book) == 0) {
            throw BusinessException.databaseError();
        }
    }

    /**
     * 减少指定图书的库存。
     * <p>将 {@code bookId} 所对应的图书的库存减少 {@code stock} 。 </p>
     *
     * @param bookId 图书ID。
     * @param stock 减少的库存数量。
     * @return 如果操作成功，则返回更改后的 {@link Book} 对象。
     * @throws BusinessException 当图书不存在，图书的库存少于 {@code stock}以及数据库操作失败时。
     */
    public Book decreaseStock(Integer bookId, Integer stock) {
        Book book = getById(bookId);
        if (book == null) {
            throw BusinessException.bookNotFound();
        }

        if (book.getStock() < stock) {
            throw BusinessException.bookOutOfStock();
        }

        book.setStock(book.getStock() - stock);

        // 增加借阅量（默认为当前值 + stock）
        book.setBorrowCount(book.getBorrowCount() + stock);

        if (!this.updateById(book)) {
            throw BusinessException.databaseError();
        }

        return book;
    }

    /**
     * 增加指定图书的库存。
     * <p>将 {@code bookId} 所对应的图书的库存增加 {@code stock} 。 </p>
     *
     * @param bookId 图书ID。
     * @param stock 增加的库存。
     * @return 如果操作成功，则返回更改后的 {@link Book} 对象。
     * @throws BusinessException 当图书不存在，当前的库存与 {@code stock} 之和大于图书总量或数据库操作失败时。
     */
    public Book increaseStock(Integer bookId, Integer stock) {
        Book book = getById(bookId);
        if (book == null) {
            throw BusinessException.bookNotFound();
        }

        if (book.getStock() + stock > book.getTotal()) {
            throw BusinessException.bookStockOverflow();
        }

        book.setStock(book.getStock() + stock);
        if (!this.updateById(book)) {
            throw BusinessException.databaseError();
        }

        return book;
    }


    /**
     * 模糊查询书籍
     *
     * @return 所有相关书籍。
     */
    public List<Book> searchBooks(String keyword) {
        return this.lambdaQuery()
                .like(Book::getTitle, keyword)
                .or().like(Book::getAuthor, keyword)
                .or().like(Book::getIsbn, keyword)
                .list();
    }


    /**
     * 获取推荐书籍。
     *
     * @return 推荐书籍。
     **/
    public List<Map<String, Object>> suggestBooks(String keyword, int limit) {
        return this.lambdaQuery()
                .select(Book::getId, Book::getTitle, Book::getAuthor)
                .like(Book::getTitle, keyword)
                .or().like(Book::getAuthor, keyword)
                .or().like(Book::getIsbn, keyword)
                .last("limit " + limit)
                .list()
                .stream()
                .map(book -> {
                    Map<String, Object> map = new HashMap<>();
                    map.put("id", book.getId());
                    map.put("title", book.getTitle());
                    map.put("author", book.getAuthor());
                    return map;
                }).collect(Collectors.toList());
    }

    /**
     * 判断是否存在对应的图书。
     *
     * @param bookId 图书ID。
     * @return 如果图书ID对应的图书存在，则返回 {@code true} ；否则返回 {@code false} 。
     */
    public boolean existBook(Integer bookId) {
        return getById(bookId) != null;
    }
}